#pragma once

#include <iomanip>
#if defined (__linux__)
#include <jsoncpp/json/json.h>
#elif defined (__APPLE__)
#include <json/json.h>
#endif
#include "except.hpp"

namespace pharmacy_server
{
    struct json_util
    {
        static Json::Value deserialize(const std::string& str)
        {
            Json::Value root;
            std::unique_ptr<Json::CharReader> cr(Json::CharReaderBuilder().newCharReader());

            std::string errs;
            if (!cr->parse(str.c_str(), str.c_str() + str.size(), &root, &errs))
                throw except("deserialize parse error " + errs);

            return root;
        }

        static std::string serialize(const Json::Value& root)
        {
            // Json::FastWriter writer;
            // return writer.write(root);

            std::unique_ptr<Json::StreamWriter> sw(Json::StreamWriterBuilder().newStreamWriter());
            std::stringstream res;

            if (sw->write(root, &res) != 0)
                throw except("serialize write error");

            return res.str();
        }
    };

    struct time_util
    {
        static time_t now()
        {
            return std::time(nullptr);
        }

        static std::string time2str(time_t time)
        {
            struct tm t;
#if defined (_WIN32) || defined (_WIN64)
            localtime_s(&t, &time);
#else
            localtime_r(&time, &t);
#endif
            char buf[32] = { 0 };
            strftime(buf, 32, "%F", &t); // %Y-%m-%d %H:%M:%S == %F %T

            return buf;
        }

        static time_t str2time(const std::string& str)
        {
            struct tm t = {};
            std::istringstream ss(str);
            ss >> std::get_time(&t, "%F");
            return std::mktime(&t);
        }

    };
}
